﻿
namespace HSS
{
	#region Using Directives
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Globalization;
	using System.IO;
	using System.Reflection;
	using System.Resources;
	using System.Threading;
	using System.Windows;
	using System.Windows.Documents;
	using System.Windows.Media.Imaging;
	using System.Windows.Resources;
	#endregion

	#region ResourceProvider
	/// <summary>
	/// A ResourceProvider Utility for accessing Silverlight and Webservice Resources
	/// </summary>
	[System.Diagnostics.DebuggerStepThroughAttribute()]
	public sealed class ResourceProvider
	{
		#region Fields
		static readonly ResourceManager solLocalStrings = new ResourceManager("HSS.Resources.Strings", typeof(ResourceProvider).Assembly);
		static List<ResourceManager> strings = new List<ResourceManager>();
		static Dictionary<string, object> localStrings = new Dictionary<string, object>();
		static readonly object setLock = new object();
		#endregion

		#region Constructors
		private ResourceProvider()
		{

		}
		/// <summary>
		/// Constructor
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
		static ResourceProvider()
		{
			Load();
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the culture for the ResourceManagers.
		/// </summary>		
		public static CultureInfo UICulture
		{
			get { return uiCulture; }
			set
			{
				if (uiCulture != value)
				{
					lock (setLock)
					{
						uiCulture = value;
						Load();
					}
				}
			}
		} static CultureInfo uiCulture = Thread.CurrentThread.CurrentUICulture;
		/// <summary>
		/// Gets the simple name of the currently executing Assembly
		/// </summary>
		public static string ExecutingAssemblyName
		{
			get
			{
				string asmFullName = System.Reflection.Assembly.GetExecutingAssembly().FullName;
				return new AssemblyName(asmFullName).Name;
			}
		}
		#endregion

		#region Methods

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
		internal static void Load()
		{
			localStrings.Clear();
			localStrings = new Dictionary<string, object>();
			try
			{
				ResourceSet rr = solLocalStrings.GetResourceSet(UICulture, true, true);
				foreach (var r in rr)
				{
					DictionaryEntry entry = (DictionaryEntry)r;
					localStrings.Add(entry.Key.ToString(), entry.Value);
				}
			}
			catch { }
		}

		/// <summary>
		/// Register an existing ResourceManager with the ResourceProvider.
		/// <para>NOTE: Only <c>GetString</c> is supported.</para>
		/// </summary>
		/// <param name="resxmgr">Your custom strings ResourceManager instance to register</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "resxmgr")]
		public static void RegisterResourceManager(ResourceManager resxmgr)
		{
			strings.Add(resxmgr);
		}
		/// <summary>
		/// Returns a string from the resource database, it handles localization
		/// transparent for the user.
		/// </summary>
		/// <returns>
		/// The string in the (localized) resource database.
		/// </returns>
		/// <param name="name">
		/// The name of the requested resource.
		/// </param>
		/// <param name="args">An object array that contains zero or more objects to format.</param>
		/// <exception cref="ResourceNotFoundException">
		/// Is thrown when the GlobalResource manager can't find a requested resource.
		/// </exception>
		public static string GetString(string name, params object[] args)
		{
			var value = GetString(name);
			return string.Format(UICulture, value, args);
		}
		/// <summary>
		/// Returns a string from the resource database, it handles localization
		/// transparent for the user.
		/// </summary>
		/// <returns>
		/// The string in the (localized) resource database.
		/// </returns>
		/// <param name="name">
		/// The name of the requested resource.
		/// </param>
		/// <exception cref="ResourceNotFoundException">
		/// Is thrown when the GlobalResource manager can't find a requested resource.
		/// </exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
		public static string GetString(string name)
		{
			lock (setLock)
			{
				if (localStrings != null && localStrings.ContainsKey(name) && localStrings[name] != null)
					return localStrings[name].ToString();

				string s = null;

				foreach (var resourceManger in strings)
				{
					try { s = resourceManger.GetString(name, UICulture); }
					catch (Exception) { }

					if (s != null)
						break;
				}

				if (s == null)
					throw new ResourceNotFoundException("string >" + name + "<");

				return s;
			}
		}
		/// <summary>
		/// Attempts to retrieve a Style object from the Application ResourceDictionary.
		/// </summary>
		/// <param name="styleKey">The key of the Style to retrieve</param>
		/// <returns>The found style; otherwise null</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
		public static Style GetAppStyle(string styleKey)
		{
			Style style = null;
			try
			{
				style = Application.Current.Resources[styleKey] as Style;
			}
			catch
			{
				style = null;
			}
			return style;
		}
		/// <summary>
		/// Gets the simple name of the Assembly from the specified <see cref="Type"/>
		/// </summary>
		public static string GetAssemblyName(Type type)
		{
			Guard.ArgumentNotNull(type, "type");
			string asmFullName = type.Assembly.FullName;
			return new AssemblyName(asmFullName).Name;
		}
		/// <summary>
		/// Attempts to retreive a component Resource Stream.
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource.</param>
		/// <returns>A StreamResourceInfo if found; otherwise null.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static StreamResourceInfo GetResourceStream(string relativeUri)
		{
			return GetResourceStream(relativeUri, ExecutingAssemblyName);
		}
		/// <summary>
		/// Attempts to retreive a component Resource Stream from the specified assembly.
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="assemblyName">The name of the assembly where the resource is located</param>
		/// <returns>A Resource Stream</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static StreamResourceInfo GetResourceStream(string relativeUri, string assemblyName)
		{
			StreamResourceInfo res = Application.GetResourceStream(new Uri(assemblyName + ";component/" + relativeUri, UriKind.Relative));
			if (res == null)
				res = Application.GetResourceStream(new Uri(relativeUri, UriKind.Relative));
			return res;
		}
		/// <summary>
		/// Attempts to retreive a component Resource Stream from the specified assembly.
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="assemblyName">The name of the assembly where the resource is located</param>
		/// <returns>A Resource Stream</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static Stream GetStream(string relativeUri, string assemblyName)
		{
			var res = Application.GetResourceStream(new Uri(assemblyName + ";component/" + relativeUri, UriKind.Relative));
			if (res == null)
				res = Application.GetResourceStream(new Uri(relativeUri, UriKind.Relative));

			if (res != null)
				return res.Stream;
			else
				return null;
		}
		/// <summary>
		/// Attempts to retreive a component Resource Stream from the currently executing assembly.
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <returns>A Resource Stream</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static Stream GetStream(string relativeUri)
		{
			return GetStream(relativeUri, ExecutingAssemblyName);
		}
		/// <summary>
		/// Return a Resource Bitmap from the local type
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="type">The Type where the resource is located</param>
		/// <returns>A Resource Bitmap</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static BitmapImage GetBitmap(string relativeUri, Type type)
		{
			var asmName = GetAssemblyName(type);
			var s = GetStream(relativeUri, asmName);
			if (s == null) return null;
			using (s)
			{
				var bmp = new BitmapImage();
				bmp.SetSource(s);
				return bmp;
			}
		}
		/// <summary>
		/// Return a Resource Bitmap
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="assemblyName">The name of the assembly where the resource is located</param>
		/// <returns>A Resource Bitmap</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static BitmapImage GetBitmap(string relativeUri, string assemblyName)
		{
			var s = GetStream(relativeUri, assemblyName);
			if (s == null) return null;
			using (s)
			{
				var bmp = new BitmapImage();
				bmp.SetSource(s);
				return bmp;
			}
		}
		/// <summary>
		/// Return a Resource Bitmap
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <returns>A Resource Bitmap</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static BitmapImage GetBitmap(string relativeUri)
		{
			return GetBitmap(relativeUri, ExecutingAssemblyName);
		}
		/// <summary>
		/// Gets a resource.
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="assemblyName">The name of the assembly where the resource is located</param>
		/// <returns>A Resource String</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static string GetResource(string relativeUri, string assemblyName)
		{
			Stream s = GetStream(relativeUri, assemblyName);
			if (s == null) return null;
			using (StreamReader reader = new StreamReader(s))
			{
				return reader.ReadToEnd();
			}
		}
		/// <summary>
		/// Gets a resource.
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <returns>A Resource String</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static string GetResource(string relativeUri)
		{
			return GetResource(relativeUri, ExecutingAssemblyName);
		}
		/// <summary>
		/// Return a Resource Font
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="assemblyName">The name of the assembly where the resource is located</param>
		/// <returns>A Resource Font</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static FontSource GetFontSource(string relativeUri, string assemblyName)
		{
			Stream s = GetStream(relativeUri, assemblyName);
			if (s == null) return null;
			using (s)
			{
				return new FontSource(s);
			}
		}
		/// <summary>
		/// Return a Resource Font
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <returns>A Resource Font</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static FontSource GetFontSource(string relativeUri)
		{
			return GetFontSource(relativeUri, ExecutingAssemblyName);
		}
		/// <summary>
		/// Returns a Xaml Object Tree
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <param name="assemblyName">The name of the assembly where the resource is located</param>
		/// <returns>The Xaml Object Tree</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static object GetXamlObject(string relativeUri, string assemblyName)
		{
			string str = GetResource(relativeUri, assemblyName);
			if (str == null) return null;
			object obj = System.Windows.Markup.XamlReader.Load(str);
			return obj;
		}
		/// <summary>
		/// Returns a Xaml Object Tree
		/// </summary>
		/// <param name="relativeUri">The Uri to the resource</param>
		/// <returns>The Xaml Object Tree</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static object GetXamlObject(string relativeUri)
		{
			return GetXamlObject(relativeUri, ExecutingAssemblyName);
		}
		/// <summary>
		/// Gets the absolute Uri string to a resource, relative to the Host Uri.
		/// </summary>
		/// <param name="resourceRelativeUri">The relative uri of the resource</param>
		/// <returns>The absolute Uri string.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static string GetAbsoluteUriString(string resourceRelativeUri)
		{
			return GetAbsoluteUri(resourceRelativeUri).ToString();
		}
		/// <summary>
		/// Gets the absolute Uri to a resource, relative to the Host Uri.
		/// </summary>
		/// <param name="resourceRelativeUri">The relative uri of the resource</param>
		/// <returns>The absolute Uri.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static Uri GetAbsoluteUri(string resourceRelativeUri)
		{
			var source = Application.Current.Host.Source;
			var baseUri = source.ToString().Replace(source.LocalPath, string.Empty);
			var uriBase = new Uri(baseUri);
			return new Uri(uriBase, resourceRelativeUri);
		}
		/// <summary>
		/// Gets the absolute Uri string to a resource, relative to the Host Source Uri.
		/// </summary>
		/// <param name="relativeUri">The relative uri of the resource</param>
		/// <returns>The absolute Uri string.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static string GetClientBinAbsoluteUriString(string relativeUri)
		{
			return GetClientBinAbsoluteUri(relativeUri).ToString();
		}
		/// <summary>
		/// Gets the absolute Uri to a resource, relative to the Host Source Uri.
		/// </summary>
		/// <param name="relativeUri">The relative uri of the resource</param>
		/// <returns>The absolute Uri string.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")]
		public static Uri GetClientBinAbsoluteUri(string relativeUri)
		{
			return new Uri(Application.Current.Host.Source, relativeUri);
		}
		/// <summary>
		/// Gets the Document URI of the current Html Page. Excludes the Fragment.
		/// </summary>
		/// <returns>The Document Uri.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
		public static Uri GetDocumentUri()
		{
			if (!System.Windows.Browser.HtmlPage.IsEnabled)
				return null;
			var uri = System.Windows.Browser.HtmlPage.Document.DocumentUri;
			return new Uri(uri.AbsoluteUri.Replace(uri.Fragment, string.Empty), UriKind.Absolute);
		}

		#endregion
	}
	#endregion
}
